/*
 * FieldInterpolation2D.h
 *
 *      Author: Jerome RD Soine and Christoph A Brand
 *      Institution: Schwarz goup, Institute for Theoretical Physics, Heidelberg University, Germany
 */

#ifndef FIELDINTERPOLATION2D_H_
#define FIELDINTERPOLATION2D_H_



#include <lac/vector.h>
#include <lac/full_matrix.h>
#include <lac/sparse_matrix.h>
#include <lac/solver_cg.h>
#include <lac/precondition.h>
#include <lac/constraint_matrix.h>
#include <grid/tria.h>
#include <grid/grid_generator.h>
#include <grid/grid_refinement.h>
#include <grid/tria_accessor.h>
#include <grid/tria_iterator.h>
#include <grid/tria_boundary_lib.h>
#include <dofs/dof_handler.h>
#include <dofs/dof_accessor.h>
#include <dofs/dof_tools.h>
#include <dofs/dof_iterator_selector.h>
#include <fe/fe_values.h>
#include <numerics/vectors.h>
#include <numerics/matrices.h>
#include <numerics/data_out.h>
#include <numerics/error_estimator.h>
#include <grid/grid_in.h>
#include <grid/grid_out.h>
#include <grid/grid_tools.h>
#include <base/timer.h>
#include <numerics/fe_field_function.h>
#include <base/function.h>
#include <base/geometry_info.h>

#include <fe/fe_system.h>
#include <fe/fe_q.h>


#include <fstream>
#include <iostream>

#include <string>

#include "../cell_models/ACM/geometry/base/vertex.h"
#include "../../core/SubstrateModel.h"
#include "DataContainer.h"

///surface_src/geometry/base/vertex.h"

using namespace dealii;


class FieldInterpolation2D
{
public:
  FieldInterpolation2D(Point<2> p1, Point<2> p2, unsigned int n_ref, std::string filename);
  FieldInterpolation2D(Point<2> p1, Point<2> p2, unsigned int n_ref, SubstrateModel* substrate, vector<ForceTransmission*> fts);
  FieldInterpolation2D(std::vector<double> P1, std::vector<double> P2, unsigned int n_ref, std::string filename);
  virtual ~FieldInterpolation2D();

  void generate_rectangular_mesh(Point<2>,Point<2>,unsigned int);
  void generate_rectangular_mesh(Point<2> p1, Point<2> p2,unsigned int n_refs,vector<ForceTransmission*> fts);
  void output(std::string);
  void output_force(std::string);

  unsigned int n_dofs();
  unsigned int n_vertices();

  void point_evaluation(Point<2> &point, Vector<double> &value);

  void reinitialize_values(Vector<double>);

  DoFHandler<2>::active_cell_iterator find_cell_around_point(Point<2> p);

  Vector<double> get_solution();
  void set_solution(Vector<double>);

  Triangulation<2> get_triangulation();

  DoFHandler<2>* get_dof_handler();

  void interpolate_point_field(std::vector<Vertex*>*,std::vector<Vertex>);

  void interpolate_fields(SubstrateModel* substrate,vector<ForceTransmission*> fts);

  void interpolate_force(vector<ForceTransmission*> fts);

  void read_file(std::string filename);

  void generate_vtk(std::string filename);

protected:

  Triangulation<2,2>* triangulation;

  DoFHandler<2,2>* dof_handler;

  FESystem<2>* fe;

  Vector<double>       solution;

  Vector<double>       force_solution;

  DataContainer* data_container;

  vector<Vertex*>* positions;

  vector<Vertex> displacements;

  void refine_based_on_traction_shapes(vector<ForceTransmission*> force_trans);

};




#endif /* FIELDINTERPOLATION2D_H_ */
